/*
 * Author: Kishore Reddy
 * Url: http://commonlibrarynet.codeplex.com/
 * Title: CommonLibrary.NET
 * Copyright: � 2009 Kishore Reddy
 * License: LGPL License
 * LicenseUrl: http://commonlibrarynet.codeplex.com/license
 * Description: A C# based .NET 3.5 Open-Source collection of reusable components.
 * Usage: Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using ComLib.Entities;
using ComLib.Extensions;
using ComLib.Caching;
using ComLib.Data;
using ComLib.LocationSupport;
using ComLib.ValidationSupport;



namespace ComLib.Web.Modules.Widgets
{
    
    /// <summary>
    /// WidgetInstance entity.
    /// </summary>
    public partial class WidgetInstance : ActiveRecordBaseEntity<WidgetInstance>, IEntity
    {
        /// <summary>
        /// Reference to the definition for this widget.
        /// </summary>
        public Widget Definition { get; set; }


        /// <summary>
        /// Move this instance to a new zone and/or change sort index.
        /// </summary>
        /// <param name="zone"></param>
        /// <param name="newSortIndex"></param>
        /// <param name="changeZone"></param>
        /// <param name="changeSortIndex"></param>
        public void Move(string newZone, int newSortIndex, bool changeZone, bool changeSortIndex)
        {
            if (changeZone && !string.IsNullOrEmpty(newZone))
                Zone = newZone;

            if (changeSortIndex)
                SortIndex = newSortIndex;

            Update();
        }


        /// <summary>
        /// Activate this instance.
        /// </summary>
        public void Activate()
        {
            IsActive = true;
            Update();
        }


        /// <summary>
        /// Deactivate this widget.
        /// </summary>
        public void Deactivate()
        {
            IsActive = false;
            Update();
        }


        /// <summary>
        /// Highlights this item so it stands out when displayed.
        /// </summary>
        public void Highlight()
        {
            IsHighlighted = true;
            Update();
        }


        /// <summary>
        /// Highlights this item so it stands out when displayed.
        /// </summary>
        public void UnHighlight()
        {
            IsHighlighted = false;
            Update();
        }


        protected override IValidator GetValidatorInternal()
        {
            var val = new EntityValidator((validationEvent) =>
            {
                int initialErrorCount = validationEvent.Results.Count;
                IValidationResults results = validationEvent.Results;
                WidgetInstance entity = (WidgetInstance)validationEvent.Target;
                Validation.IsStringLengthMatch(entity.Header, false, true, true, 1, 150, results, "Header");
                Validation.IsStringLengthMatch(entity.Zone, false, true, true, 1, 50, results, "Zone");
                Validation.IsStringLengthMatch(entity.Group, true, false, true, -1, 50, results, "Group");
                Validation.IsStringLengthMatch(entity.Roles, true, false, true, -1, 50, results, "Roles");
                Validation.IsStringLengthMatch(entity.Args, true, false, true, -1, 200, results, "Args");
                Validation.IsStringLengthMatch(entity.RefModel, true, false, true, -1, 20, results, "RefModel");
                Validation.IsStringLengthMatch(entity.RefName, true, false, true, -1, 50, results, "RefName");
                Validation.IsStringLengthMatch(entity.RefGroup, true, false, true, -1, 50, results, "RefGroup");
                Validation.IsStringLengthMatch(entity.RefEmail, true, false, true, -1, 50, results, "RefEmail");
                Validation.IsStringLengthMatch(entity.RefUrl, true, false, true, -1, 150, results, "RefUrl");
                Validation.IsStringLengthMatch(entity.RefSource, true, false, true, -1, 100, results, "RefSource");
                Validation.IsStringLengthMatch(entity.RefKey, true, false, true, -1, 100, results, "RefKey");
                Validation.IsStringLengthMatch(entity.RefContent, true, false, false, -1, -1, results, "RefContent");

                return initialErrorCount == validationEvent.Results.Count;
            });
            return val;
        }


        #region Life-Cycle Events
        /// <summary>
        /// Called when [before save].
        /// </summary>
        /// <param name="ctx"></param>
        /// <returns></returns>
        public override bool  OnBeforeSave(object ctx)
        {
            if (this.RefDate1 == DateTime.MinValue)
                RefDate1 = DateTime.Today;
            if (this.RefDate2 == DateTime.MinValue)
                RefDate2 = DateTime.Today;

            SetUpWidgetDefId(this.DefName, this);
            return true;
        }
        #endregion


        #region Public static Helper Methods
        /// <summary>
        /// Create a new widget instance and associate it w/ its widget.
        /// </summary>
        /// <param name="widgetTitle"></param>
        /// <param name="instance"></param>
        public static void Create(IList<WidgetInstance> instances, bool checkIfPresent)
        {
            foreach (var instance in instances)
                Create(instance.DefName, instance, checkIfPresent);
        }


        /// <summary>
        /// Create a new widget instance and associate it w/ its widget.
        /// </summary>
        /// <param name="widgetTitle"></param>
        /// <param name="instance"></param>
        public static void Create(string widgetTitle, WidgetInstance instance, bool checkIfPresent)
        {
            SetUpWidgetDefId(widgetTitle, instance);
            if (!checkIfPresent)
                Create(instance);
            else
            {
                Create(new List<WidgetInstance>() { instance }, i => i.Header, i => i.WidgetId);
            }
        }


        private static void SetUpWidgetDefId(string definitionName, WidgetInstance instance)
        {            
            IList<Widget> widgets = Widget.Find(Query<Widget>.New().Where(w => w.Title).Is(definitionName));
            if (widgets == null && widgets.Count == 0)
                throw new ArgumentException("Unknown widget with title : " + definitionName);

            // Set the widget id.
            instance.WidgetId = widgets[0].Id;
        }
        #endregion
    }



    /// <summary>
    /// Widget extensions.
    /// </summary>
    public partial class Widget : ActiveRecordBaseEntity<Widget>, IEntity
    {
        /// <summary>
        /// Names of all the distinct widgets.
        /// </summary>
        public static IList<string> Names
        {
            get
            {
                var all = Cacher.Get<IList<Widget>>("widgets_all", 30, () => GetAll());
                var names = Cacher.Get<IList<string>>("widgets_names", 30, () =>
                {
                    IList<string> widgetnames = new List<string>();
                    foreach (var widget in all)
                        widgetnames.Add(widget.Title);

                    return widgetnames;
                });
                return names;
            }
        }
    }
}
